/*
 * Grupo:		Danilo Beraldo Ireno
 * 				Flavio Augusto de Mello
 * 				Giuliano G. Maranha
 * 				Luis Fernando Junior
 *
 * Disciplina: 	Compiladores
 * Professor:	Dr. Eraldo Pereira Marinho*
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "tokens.h"
#include "keywords.h"
#include "lexer.h"

FILE *tape;
int i;
int lookahead;
int linecount = 1;
char lexeme[MAXLEN];

void skipspacesandcomments(void) {
	int head;
	while (1) {

		head = getc(tape);

		if (head == '\n') {
			linecount++;
		}

		if (!isspace(head)) {

			//skip pascal comments
			if (head == '{') {
				while ((head = getc(tape)) != '}') {
					if (head == '\n') {
						linecount++;
					}
				}
			} else {
				ungetc(head, tape);
				break;
			}
		}
	}
}

isID(void) {
	i = 0;
	lexeme[i] = toupper(getc(tape));

	if (isalpha(lexeme[i])) {
		while (isalnum(lexeme[++i] = toupper(getc(tape))));
		ungetc(lexeme[i], tape);
		lexeme[i] = 0;
		if (i = iskeyword(lexeme))
			return i;
		return ID;
	}
	ungetc(lexeme[i], tape);
	return 0;
}

isCHARCONST(void) {

	i = 0;

	if ((lexeme[i] = getc(tape)) == '\'') {

		while ((lexeme[++i] = getc(tape)) != '\'');

		return CHARCONST;

	} else {
		ungetc(lexeme[i], tape);
		lexeme[i] = 0;
		return 0;
	}
}

isASGNM(void) {
	lexeme[0] = getc(tape);
	lexeme[1] = getc(tape);

	if(lexeme[0] == ':'){
		if(lexeme[1] == '='){
			return ASGNM;
		}else{
			ungetc(lexeme[1],tape);
			ungetc(lexeme[0],tape);
			lexeme[0] = 0;
			return 0;
		}
	}else{
		ungetc(lexeme[1],tape);
		ungetc(lexeme[0],tape);
		lexeme[0] = 0;
		return 0;
	}
}

/*
 * Not Equal '<>'
 */

isNEQ(void) {

	i = 0;
	if ((lexeme[i] = getc(tape)) == '<') {
		if ((lexeme[++i] = getc(tape)) == '>') {

			return NEQ;
		} else {
			ungetc(lexeme[i], tape);
			ungetc(lexeme[--i], tape);
			lexeme[0] = 0;
			return 0;
		}
	} else {

		ungetc(lexeme[i], tape);
		lexeme[0] = 0;
		return 0;
	}
}

isGEQ(void) {

	lexeme[0] = getc(tape);
	lexeme[1] = getc(tape);

	if(lexeme[0] == '>'){
		if(lexeme[1] == '='){
			return GEQ;
		}else{
			ungetc(lexeme[1],tape);
			ungetc(lexeme[0],tape);
			return 0;
		}
	}else{
		ungetc(lexeme[1],tape);
		ungetc(lexeme[0],tape);
		return 0;
	}
}

isLEQ(void) {

	i = 0;
	if ((lexeme[i] = getc(tape)) == '<') {
		if ((lexeme[++i] = getc(tape)) == '=') {

			return LEQ;
		} else {
			ungetc(lexeme[i], tape);
			ungetc(lexeme[--i], tape);
			lexeme[0] = 0;
			return 0;
		}
	} else {

		ungetc(lexeme[i], tape);
		lexeme[0] = 0;
		return 0;
	}
}

isUINT(void) {

	i = 0;

	if (isdigit((lexeme[i] = getc(tape)))) {

		while (isdigit((lexeme[++i] = getc(tape))));
		ungetc(lexeme[i], tape);
		lexeme[i] = 0;
		return UINT;

	} else {
		ungetc(lexeme[i], tape);
		lexeme[i] = 0;
		return 0;
	}
}

isSIGNAL(void) {

	lexeme[0] = getc(tape);

	if (lexeme[0] == '+' || lexeme[0] == '-') {
		lexeme[1] = 0;
		return SIGNAL;
	} else {
		ungetc(lexeme[0], tape);
		lexeme[0] = 0;
		return 0;
	}
}

isDOTDOT(void) {

	i = 0;

	if ((lexeme[i] = getc(tape)) == '.') {

		if ((lexeme[++i] = getc(tape)) == '.') {

			return DOTDOT;

		} else {
			ungetc(lexeme[i], tape);
			ungetc(lexeme[--i], tape);
			lexeme[i] = 0;
			return 0;
		}
	} else {
		ungetc(lexeme[i], tape);
		lexeme[i] = 0;
		return 0;
	}
}

gettoken(void) {
	int token;
	int head;
	skipspacesandcomments();
	if (token = isID()){
		return token;
	}
	if (token = isASGNM()){
		return token;
	}
	if (token = isGEQ()){
		return token;
	}
	if (token = isLEQ()){
		return token;
	}
	if (token = isNEQ()){
		return token;
	}
	if (token = isCHARCONST()){
		return token;
	}
	if (token = isUINT()){
		return token;
	}
	if (token = isDOTDOT()){
		return token;
	}
	if (token = isSIGNAL()){
		return token;
	}
	lexeme[1] = 0;
	lexeme[0] = getc(tape);
	return lexeme[0];
}

void match(int expected) {
	if (expected == lookahead) {
		lookahead = gettoken();
	} else {
		//fprintf(stderr, "token mismatch expected %d found %d  aborting \n line: %d",expected, lookahead,linecount);
		 error(expected, lookahead, linecount);
		//exit(-1);
	}
}

